const { Service } = require('egg');
const { v4: uuidV4 } = require('uuid');
const moment = require('moment');
const approval_table = 'inventory_approval',
  approval_process_table = 'inventory_approval_process',
  inventory_table = 'inventory',
  product_table = 'product',
  barcode_table = 'barcode',
  user_table = 'user';

class ApprovalService extends Service {

  async insert(barcode_id, number, type, product_id, status, title) {
    const ctx = this.ctx;
    const trx = await ctx.app.knex.transaction();
    try {
      const { id: user_id } = ctx.session;
      const time = moment();
      const approvalInstance = {
        barcode_id, number, product_id,
        status,
        type,
        title,
        uuid: uuidV4(),
        create_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        update_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        create_by: user_id,
        update_by: user_id,
        is_delete: 0,
      };

      await trx(approval_table).insert(approvalInstance);

      const approvalProcessInstance = {
        uuid: uuidV4(),
        approval_id: approvalInstance.uuid,
        title,
        content: title,
        reason: '系统创建',
        status: 0,
        create_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        update_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        create_by: user_id,
        update_by: user_id,
      };


      await trx(approval_process_table).insert(approvalProcessInstance);

      await trx.commit();
      return approvalInstance;
    } catch (error) {
      await trx.rollback();
      throw error;
    }
  }

  // 拒绝审批
  async refuse(approval_id) {
    const ctx = this.ctx;
    const trx = await ctx.app.knex.transaction();
    try {
      const time = moment();
      const { id: user_id } = ctx.session;
      const is_operation = await ctx.app.knex(approval_table).select('*').where({ uuid: approval_id })
        .andWhereNot({ status: 0 })
        .first();
      if (is_operation) {
        throw new Error('当前审批已经被审核');
      }

      const instance = await ctx.app.knex(approval_process_table).select('*').where({ approval_id, status: 0 })
        .first();

      instance.update_time = moment(time).format('YYYY-MM-DD HH:mm:ss');
      instance.update_by = user_id;
      instance.status = 2;
      instance.title = '拒绝入库';
      instance.uuid = uuidV4();


      const approval = await ctx.app.knex(approval_table).select('barcode_id', 'number', 'type', 'product_id').where({ uuid: instance.approval_id })
        .first();
      approval.update_time = moment(time).format('YYYY-MM-DD HH:mm:ss');
      approval.update_by = user_id;
      approval.status = 2;
      await trx(approval_process_table).insert(instance);
      await trx(approval_table).update(approval);

      await trx.commit();
      return instance;
    } catch (error) {
      await trx.rollback();
      throw error;
    }
  }

  // 通过审批
  async pass(approval_id) {
    const ctx = this.ctx;
    const trx = await ctx.app.knex.transaction();
    try {
      const time = moment();
      const { id: user_id } = ctx.session;
      const is_operation = await ctx.app.knex(approval_process_table).select('*').where({ approval_id })
        .whereNot({ status: 0 })
        .first();
      if (is_operation) {
        throw new Error('当前审批已被审核');
      }

      const instance = await ctx.app.knex(approval_process_table).select('*').where({ approval_id, status: 0 })
        .first();

      instance.update_time = moment(time).format('YYYY-MM-DD HH:mm:ss');
      instance.create_time = moment(time).format('YYYY-MM-DD HH:mm:ss');
      instance.create_by = user_id;
      instance.update_by = user_id;
      instance.status = 1;
      instance.title = '同意';
      instance.uuid = uuidV4();

      await trx(approval_process_table).insert(instance);

      const approval = await ctx.app.knex(approval_table).select('barcode_id', 'number', 'type', 'product_id').where({ uuid: instance.approval_id })
        .first();

      const inventoryInstance = {
        uuid: uuidV4(),
        barcode_id: approval.barcode_id,
        product_id: approval.product_id,
        number: approval.number,
        type: approval.type,
        create_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        update_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        update_by: user_id,
        create_by: user_id,
        is_delete: 0,
      };

      approval.status = 1;
      approval.update_time = moment(time).format('YYYY-MM-DD HH:mm:ss');
      approval.update_by = user_id;

      await trx(approval_table).update(approval);
      await trx(inventory_table).insert(inventoryInstance);

      await trx.commit();
      return instance;
    } catch (error) {
      await trx.rollback();
      throw error;
    }
  }

  // 审批列表

  async list(name, barcode, status, type, order, method, pageIndex, pageSize) {
    const ctx = this.ctx;
    try {
      const sql = ctx.app.knex().select('t1.uuid', 't1.barcode_id', 't2.content as barcode',
        't2.product_id', 't3.name as product_name', 't1.number', 't1.type', 't1.create_time',
        't1.update_time', 't4.name as create_name', 't5.name as update_name'
      )
        .from(`${approval_table} as t1`)
        .leftJoin(`${barcode_table} as t2`, function() {
          this.on('t2.uuid', '=', 't1.barcode_id');
        })
        .leftJoin(`${product_table} as t3`, function() {
          this.on('t2.product_id', '=', 't3.uuid');
        })
        .leftJoin(`${user_table} as t4`, function() {
          this.on('t1.create_by', '=', 't4.uuid');
        })
        .leftJoin(`${user_table} as t5`, function() {
          this.on('t1.update_by', '=', 't5.uuid');
        })
        .where('t1.is_delete', 0);

      const countSql = ctx.app.knex().count('t1.uuid as count')
        .from(`${approval_table} as t1`)
        .leftJoin(`${barcode_table} as t2`, function() {
          this.on('t2.uuid', '=', 't1.barcode_id');
        })
        .leftJoin(`${product_table} as t3`, function() {
          this.on('t2.product_id', '=', 't3.uuid');
        })
        .where('t1.is_delete', 0);


      if (name) {
        sql.whereLike('t3.name', `%${name}%`);
        countSql.whereLike('t3.name', `%${name}%`);
      }

      if (barcode) {
        sql.whereLike('t2.content', `%${barcode}%`);
        countSql.whereLike('t2.content', `%${barcode}%`);
      }

      if (status) {
        sql.andWhere(`t1.status = ${status}`);
        countSql.andWhere(`t1.status = ${status}`);
      }

      if (type) {
        sql.where('t1.type', type);
        countSql.where('t1.type', type);
      }

      const list = await sql.orderBy(order, method).limit(Number(pageSize)).offset((Number(pageIndex) - 1) * Number(pageSize));
      const count = await countSql.first();

      const result = {
        list,
        count: count.count,
      };

      return result;
    } catch (error) {
      throw error;
    }
  }

  async info(id) {
    const ctx = this.ctx;
    try {
      const list = await ctx.app.knex().select('t1.title', 't4.name as product_name', 't3.content as barcode_name',
        't1.content', 't1.reason', 't1.status', 't1.create_time', 't1.update_time', 't5.name as create_name',
        't6.name as update_time'
      )
        .from(`${approval_process_table} as t1`)
        .leftJoin(`${approval_table} as t2`, function() {
          this.on('t1.approval_id', '=', 't2.uuid');
        })
        .leftJoin(`${barcode_table} as t3`, function() {
          this.on('t2.barcode_id', '=', 't3.uuid');
        })
        .leftJoin(`${product_table} as t4`, function() {
          this.on('t4.uuid', '=', 't3.product_id');
        })
        .leftJoin(`${user_table} as t5`, function() {
          this.on('t1.create_by', '=', 't5.uuid');
        })
        .leftJoin(`${user_table} as t6`, function() {
          this.on('t1.update_by', '=', 't6.uuid');
        })
        .where('t1.approval_id', id);


      const count = await ctx.app.knex().count('t1.uuid as count')
        .from(`${approval_process_table} as t1`)
        .where('t1.approval_id', id)
        .first();


      const result = {
        list,
        count: count.count,
      };

      return result;

    } catch (error) {
      throw error;
    }
  }
}


module.exports = ApprovalService;
